package com.miaosmart.controller;

import com.miaosmart.common.convention.exception.ClientException;
import com.miaosmart.common.convention.exception.ServiceException;
import com.miaosmart.common.convention.result.Result;
import com.miaosmart.common.convention.result.Results;
import com.miaosmart.dto.ModelDTO;
import com.miaosmart.dto.req.CreateSessionReqDTO;
import com.miaosmart.dto.req.UpdateSessionTitleReqDTO;
import com.miaosmart.dto.resp.CreateSessionRespDTO;
import com.miaosmart.dto.resp.GetSessionsRespDTO;
import com.miaosmart.service.ChatService;
import com.miaosmart.util.AliOssUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @Author: miaomaster
 * @Description: 对话控制器
 */
@RestController
@RequiredArgsConstructor
@Slf4j
public class ChatController {

    private final ChatService chatService;

    private final VectorStore vectorStore;

    private final AliOssUtil aliOssUtil;

    /**
     * 创建新会话
     */
    @PostMapping("/sessions")
    public Result<CreateSessionRespDTO> createSession(@RequestBody CreateSessionReqDTO requestParam) {
        return Results.success(chatService.createSession(requestParam.getTitle()));
    }

    /**
     * 获取会话列表
     */
    @GetMapping("/sessions")
    public Result<List<GetSessionsRespDTO>> getSessions() {
        return Results.success(chatService.getSessions());
    }

    /**
     * 获取单个会话详情
     */
    @GetMapping("/sessions/{sessionId}")
    public Result<CreateSessionRespDTO> getSession(@PathVariable Long sessionId) {
        return Results.success(chatService.getSession(sessionId));
    }




    /**
     * 获取可用模型列表
     */
    @GetMapping("/models")
    public Result<List<ModelDTO>> getModels() {
        return Results.success(chatService.getModels());
    }

    /**
     * 切换模型
     */
    @PutMapping("/sessions/{sessionId}/model")
    public Result<Void> switchModel(
            @PathVariable Long sessionId,
            @RequestBody ModelDTO model) {
        chatService.switchModel(sessionId, model);
        return Results.success();
    }

    /**
     * 更新会话标题
     */
    @PutMapping("/sessions/{sessionId}/title")
    public Result<Void> updateSessionTitle(
            @PathVariable Long sessionId,
            @RequestBody UpdateSessionTitleReqDTO requestParam) {
        chatService.updateSessionTitle(sessionId, requestParam.getTitle());
        return Results.success();
    }

    /**
     * 删除会话
     */
    @DeleteMapping("/sessions/{sessionId}")
    public Result<Void> deleteSession(@PathVariable Long sessionId) {
        chatService.deleteSession(sessionId);
        return Results.success();
    }

    /**
     * 流式聊天接口
     */
    @PostMapping(value = "/sessions/{sessionId}/messages", produces = MediaType.TEXT_PLAIN_VALUE)
    public Flux<String> chatStream(
            @PathVariable Long sessionId,
            @RequestParam String content) {
        return chatService.streamMessage(sessionId, content);
    }

    @PostMapping(value = "/sessions/{sessionId}/upload")
    public Result<Void> uploadPdfFile(@PathVariable Long sessionId, @RequestParam("file") MultipartFile file) {
        try {
            // 1. 校验文件是否为PDF格式
            if (!Objects.equals(file.getContentType(), "application/pdf")) {
                throw new ClientException("只支持上传PDF文件");
            }

            //原始文件名
            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || originalFilename.isEmpty()) {
                throw new ClientException("文件名不能为空");
            }
            //截取原始文件名的后缀   dfdfdf.png
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            //构造新文件名称：防止上传到阿里云的文件，因为名字重复导致覆盖的问题
            String objectName = UUID.randomUUID().toString() + extension;

            // 上传文件到OSS，返回的URL已经是自定义域名（如果配置了的话）
            String filePath = aliOssUtil.upload(file.getBytes(), objectName);

            // 3.写入向量库，添加会话ID标识
            this.writeToVectorStore(file.getResource(), sessionId);
            
            // 4.保存文件消息到数据库
            chatService.saveFileMessage(sessionId, originalFilename, filePath);

        } catch (Exception e) {
            log.error("Failed to upload PDF.", e);
            throw new ServiceException("上传文件失败！");
        }
        return Results.success();

    }



    private void writeToVectorStore(Resource resource, Long sessionId) {
        // 1.创建PDF的读取器
        PagePdfDocumentReader reader = new PagePdfDocumentReader(
                resource, // 文件源
                PdfDocumentReaderConfig.builder()
                        .withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
                        .withPagesPerDocument(1) // 每1页PDF作为一个Document
                        .build()
        );
        // 2.读取PDF文档，拆分为Document
        List<Document> documents = reader.read();
        
        // 3.为每个文档添加会话ID元数据，实现会话隔离
        documents.forEach(document -> {
            document.getMetadata().put("sessionId", sessionId.toString());
            document.getMetadata().put("uploadTime", System.currentTimeMillis());
        });
        
        // 4.写入向量库
        vectorStore.add(documents);
    }




}
